package com.divit.springboot.application.controller;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.divit.springboot.application.utils.HkUtils;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.*;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import com.divit.springboot.application.util.CandidatesUtil;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@CrossOrigin
@Slf4j
@RestController
@RequestMapping(value = "/api/v1")
public class ApiRestController {
	private static final String ARTEMIS_PATH = "/artemis";
  private static final int SOCKET_TIME_OUT = 60000;
  //连接超时时间,这个时间定义了通过网络与服务器建立连接的超时时间，也就是取得了连接池中的某个连接之后到接通目标url的连接等待时间。发生超时，会抛出ConnectionTimeoutException异常
  private static final int CONNECT_TIME_OUT = 60000;
  private static List<NameValuePair> createParam(Map<String, Object> param) {
    //建立一个NameValuePair数组，用于存储欲传送的参数
    List<NameValuePair> nvps = new ArrayList<NameValuePair>();
    if(param != null) {
      for(String k : param.keySet()) {
        nvps.add(new BasicNameValuePair(k, param.get(k).toString()));
      }
    }
    return nvps;
  }
	static {
		ArtemisConfig.host = "10.13.155.11";// 代理API网关nginx服务器ip端口
		ArtemisConfig.appKey = "22298596";// 秘钥appkey
		ArtemisConfig.appSecret = "crqRhfDeCJHfaRGzfxLk";// 秘钥appSecret
	}

	private String getResponse(String indexCode) {
		JSONObject jsonBody = new JSONObject();
		jsonBody.put("cameraIndexCode", indexCode);
		jsonBody.put("streamType", 0);
		jsonBody.put("protocol", "rtsp");
		jsonBody.put("transmode", 1);
		jsonBody.put("expand", "transcode=0");
		jsonBody.put("streamform", "rtp");
		String result=publicHkInterface(jsonBody,"/api/video/v2/cameras/previewURLs");
		return result;
	}

  @GetMapping(value = "/video/rtspReal.flv",produces = {"video/x-flv;charset=UTF-8"})
  public void flvRtspReal(HttpServletResponse response, HttpServletRequest request){

    AsyncContext asyncContext = request.startAsync();
    asyncContext.setTimeout(0);

    String rtspUrl = HkUtils.toRtspUrl("10.13.155.160", "80", "admin", "hx123456","0");
    try {
      HkUtils.rtspToFlv(rtspUrl,asyncContext);
    }catch (Exception e){
      e.printStackTrace();
    }
  }

	public static String publicHkInterface(JSONObject jsonBody,String url){
		final String getCamsApi = ARTEMIS_PATH +url;
		Map<String, String> path = new HashMap<String, String>(2);
		path.put("https://", getCamsApi);
		// post请求application/json类型参数
		String result = ArtemisHttpUtil.doPostStringArtemis(path,jsonBody.toJSONString(),null,null,"application/json",null);
//		return  result;
//		String tst =  "{\"code\":\"0\",\"msg\":\"success\",\"data\":{\"url\":\"rtsp://10.13.155.11:554/openUrl/I6H13W0\"}}";
		JSONObject jsonObject = JSON.parseObject(result);
		return  jsonObject.getJSONObject("data").getString("url");
	}

  public static String getNormalPost(String url, Map<String, Object> param, Map<String, Object> headers) throws Exception {
    //目前HttpClient最新版的实现类为CloseableHttpClient
    CloseableHttpClient client = HttpClients.createDefault();
    CloseableHttpResponse response = null;
    HttpEntity entity=null;
    try {
      if(param != null) {
        //建立Request的对象，一般用目标url来构造，Request一般配置addHeader、setEntity、setConfig
        HttpPost req = new HttpPost(url);
        entity=new UrlEncodedFormEntity(createParam(param), Consts.UTF_8);
        //setHeader,添加头文件
        Set<String> keys = headers.keySet();
        for (String key : keys) {
          req.setHeader(key, headers.get(key).toString());
        }
        //setConfig,添加配置,如设置请求超时时间,连接超时时间
        RequestConfig reqConfig = RequestConfig.custom().setSocketTimeout(SOCKET_TIME_OUT).setConnectTimeout(CONNECT_TIME_OUT).build();
        req.setConfig(reqConfig);
        //setEntity,添加内容
        req.setEntity(entity);
        //执行Request请求,CloseableHttpClient的execute方法返回的response都是CloseableHttpResponse类型
        //其常用方法有getFirstHeader(String)、getLastHeader(String)、headerIterator（String）取得某个Header name对应的迭代器、getAllHeaders()、getEntity、getStatus等
        response = client.execute(req);
        entity =  response.getEntity();
        //用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串,防止服务器返回的数据带有中文,所以在转换的时候将字符集指定成utf-8就可以了
        String result= EntityUtils.toString(entity, "UTF-8");
        if(response.getStatusLine().getStatusCode()==200){
          return result;
        }else{
          return "error";
        }
      }
      return "error";
    } catch(Exception e) {
      throw new Exception();
    }finally{
      //一定要记得把entity fully consume掉，否则连接池中的connection就会一直处于占用状态
      EntityUtils.consume(entity);
    }
  }

	@GetMapping(value = "/candidates/auth")
	public String fetchCandidates() {
    Map<String, Object> json = new HashMap<>();
		json.put("password", "111");
		json.put("grant_type", "password");
		json.put("client_secret", "111");
		json.put("client_id", "center6");
		json.put("usemame", "mgr");

    Map<String, Object> headers = new HashMap<>();
		try {
			String result = getNormalPost("http://10.13.130.198/auth/oauth/token", json, headers);
			JSONObject jsonObject = JSON.parseObject(result);
			return  jsonObject.toJSONString();
		} catch (Exception e) {
			e.printStackTrace();
			return "error";
		}
	}

	@GetMapping(value = "/candidates/{indexCode}")
	public String fetchCandidates(@PathVariable String indexCode) {
		return getResponse(indexCode);
	}

}
